<?xml version="1.0" encoding="UTF-8"?>
<doc>
<title>呼叫剧本段落功能（SubRoutine）的使用</title>


<para>
<ptitle>SubRoutine 是什么，可以吃吗？</ptitle>
　SubRoutine 是指、在剧本中的某处「呼叫」其他剧本段落的功能。SubRoutine呼叫出的剧本段落在执行完后、就会返回原来的剧本。<r/>
<r/>
　这和宏（Macro） <comlink href="Macro"/> 的功能类似、但 SubRoutine 一般用于执行比较复杂的操作、而 Macro 则相对简单一些。（例如， Macro 中禁止使用标签）<r/>
</para>

<para>
<ptitle>SubRoutine 的基本使用方法</ptitle>
　SubRoutine 功能，要求呼叫的剧本段必须是以 标签（Label）作为开头的。而段落结束，需要返回原来的剧本，则是以 <kw>return</kw> 指令作为结束符号的。要进行呼叫，请使用 <kw>call</kw> 指令。<r/>
　请看以下的例子。<r/>
<bq>
[wait time=200]<r/>
*start|开始<r/>
[cm]<r/>
要呼叫其他的剧本了哦。[l][r]<r/>
<b>[call target=*subroutine]</b><r/>
呼叫完毕，返回原来的地方了。<r/>
[s]<r/>
<r/>
<b>*subroutine</b><r/>
我是被呼叫的剧本段，而这就是 subroutine 功能了。[l][r]<r/>
点鼠标就会回到原来的地方了。[l][r]<r/>
<b>[return]</b><r/>
</bq>
<r/>
　那么、执行这个例子的时候、「要呼叫其他的剧本了哦。」的消息后，会显示的是「我是被呼叫的剧本段。」、「点鼠标就会回到原来的地方了。」对话后点鼠标、会显示「呼叫完毕，返回原来的地方了。」。<r/>
　也就是说、call 指令执行后，除了跳转到呼叫的剧本段以外、也会将之前的剧本位置进行记录、而使用 return 指令后、就会返回之前记录的位置了 ( 这种自动记录被称为「<kw>Call Stack</kw>」)。<r/>
　在以上的例子里、<tt>*subroutine</tt> 到 <tt>[return]</tt> 之间的段落，就是「subroutine」了。<r/>
<r/>
　在一个 subroutine 段落中，还可以继续呼叫其他的 subroutine 。这种呼叫可以一层一层地积累 ( return 之前再进行 call  ) ，没有呼叫层数的限制。（提示：就算是这样，多层套叠很容易导致出错。可能的话，请尽量用jump而不用call。）<r/>
<r/>
　另外，除了「使用选项分歧」的场合之类需要用 [cm] 消除文字外，假如不是保存标签 (带有 | 的标签) ，呼叫出的段落标签后面不带 [cm] 也无所谓的。（提示：不用理会这句，[cm] 能不用尽量不用。）<r/>
<r/>
<r/>
　Call Stack 记录的内容包括：剧本档名、最近的标签名、以及 call 指令距离该标签的行数、而并不是记录 call 指令的具体内容。请注意：假如在 debug 之类的情况下，改变了剧本档，可能会导致返回的时候，无法回到正确的位置。<r/>
　另外，请尽量不要将 subroutine 的开头标签当作存储标记 (带有 | 的标签) 用，在 subroutine 中，也不要创建存储标记比较好。<r/>
</para>

<para>
<ptitle>subroutine 相关的注意事项</ptitle>
　在某个剧本段落中，使用 call 呼叫自身的话，就会陷入死循环。<r/>
　call 与 return 没有一一对应的话、Call Stack 就会不断积累、有可能会造成 return 之后不是返回预期的标签的错误、请千万注意。<r/>
<r/>
　此外还有、请小心如下的例子<r/>
<r/>
<bq>
*subroutine<r/>
・・・<r/>
[if exp="f.flag1"]<b>[jump target=*otherplaces1]</b>[endif]<r/>
[if exp="f.flag2"]<b>[jump target=*otherplaces2]</b>[endif]<r/>
・・・<r/>
[return]<r/>
<r/>
*otherplaces1<r/>
・・・<r/>
[return]<r/>
<r/>
*otherplaces2<r/>
;这段落里没有 return 指令・・・<r/>
</bq>
<r/>
　这是 subroutine 段落中，又跳转到其他地方的情况。假如是跳转到 otherplaces1 的情况、由于有 return 的标记，保持了 call 〜 return 的平衡。但是、假如跳转到了 otherplaces2 、段落里没有 return 指令出现、这个 subroutine 就变成了「无法返回」的状态。也就是说、call 〜 return 的平衡没有维持。<r/>
<r/>
　如果、执行完毕后不想返回原来的呼叫处、而是想要返回其他的地方、return 指令也拥有 storage 和 target 属性、利用它们可以返回到任意位置。<r/>
</para>
</doc>